package com.sky.aspect;


import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component
@Aspect
@Slf4j
public class AutoFillAspect {

    @Before("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void before(JoinPoint jp) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        log.info("开始公共字段填充...");

        //1.获取原始方法上的注解AutoFill 对象，目的是区分inset和update操作
        //1.1获取原始方法签名对象（aop提供的签名对象）
        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        //1.2获取原始方法上的注解
        AutoFill autoFill = methodSignature.getMethod().getAnnotation(AutoFill.class);
        //1.2获取里面操作类型对象
        OperationType operationType = autoFill.value();

        //2获取原始方法参数对象Employee
        Object[] objects = jp.getArgs();
        //安全判断，不能为空
        if(objects==null || objects.length==0){
            log.info("当前方法没有合适的参数进行公共字段填充");
            return;
        }
        //获取第一个参数对象
        Object object = objects[0];
        Class clazz = object.getClass();

        //3.对参数对象进行填充
        //3.0  准备填充数据
        Long empId = BaseContext.getCurrentId();
        LocalDateTime now = LocalDateTime.now();
        //3.1填充修改人和修改时间
        //反射获取指定方法语法：clazz.getMethod(方法名，参数类型列表)
        Method setUpdateUserMethod = clazz.getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
        Method setUpdateTimeMethod = clazz.getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
        setUpdateUserMethod.invoke(object,empId);
        setUpdateTimeMethod.invoke(object,now);
        //3.2  如果insert操作，再填充创建时间和创建人
        if(operationType == OperationType.INSERT){
            Method setCreateTimeMethod = clazz.getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method setCreateUserMethod = clazz.getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            setCreateUserMethod.invoke(object,empId);
            setCreateTimeMethod.invoke(object,now);
        }
    }
}
